package com.shine.app;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import android.app.Application;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.shine.app.bean.GolfCourseBean;
import com.shine.app.bean.GolfCourseDetailBean;
import com.shine.app.bean.MyFavoriteBean;
import com.shine.app.bean.MyReviewBean;
import com.shine.app.bean.MyTeeTimesBean;
import com.shine.app.bean.PlaceNearBean;
import com.shine.app.bean.ReviewBean;
import com.shine.app.bean.SearchBean;
import com.shine.app.bean.UserBean;
import com.shine.app.bean.UserInfoBean;
import com.shine.app.bean.request.ConfirmRegisterUserBean;
import com.shine.app.bean.request.ConfirmUnregisterUserBean;
import com.shine.app.bean.request.CredentialBean;
import com.shine.app.bean.request.ExternalAccount;
import com.shine.app.bean.request.FindBookingBean;
import com.shine.app.bean.request.FindTeeTimesBean;
import com.shine.app.bean.request.LocationNearBean;
import com.shine.app.bean.request.PaymentRegisterUserBean;
import com.shine.app.bean.request.PaymentUnregisterUserBean;
import com.shine.app.bean.request.ReviewsUpdateBean;
import com.shine.app.bean.request.ReviewsWriteBean;
import com.shine.app.bean.request.SignUpBean;
import com.shine.app.bean.request.UpdatePasswordBean;
import com.shine.app.bean.request.UpdateProfileBean;
import com.shine.app.bean.request.ValidateBean;
import com.shine.app.bean.responses.AuthenticateUserResponse;
import com.shine.app.bean.responses.BookingConfirmResponse;
import com.shine.app.bean.responses.BookingConfirmationResponse;
import com.shine.app.bean.responses.FindTeeTimeListViewResponse;
import com.shine.app.bean.responses.FindTeeTimePriceResponse;
import com.shine.app.bean.responses.GetMyFavoriteResponse;
import com.shine.app.bean.responses.GetMyReviewsResponse;
import com.shine.app.bean.responses.GetMyTeeTimesResponse;
import com.shine.app.bean.responses.GolfCourseDetailResponse;
import com.shine.app.bean.responses.GolferReviewResponse;
import com.shine.app.bean.responses.PlaceNearResponse;
import com.shine.app.bean.responses.ReviewsWriteResponse;
import com.shine.app.bean.responses.TeeTimesResponse;
import com.shine.app.bean.responses.UpdateUserProfileResponse;
import com.shine.app.bean.responses.ValidateResponse;
import com.shine.app.bean.responses.ViewMyGolfResponse;
import com.shine.app.commons.Constant;
import com.shine.app.commons.StringUtils;
import com.shine.app.network.OpenTeeClientProxy;

public class AppContext extends Application {
	private boolean login = false;
	private AppConfig appConfig = new AppConfig();
	protected static double longitude = 0;
	protected static double latitude = 0;
	protected static boolean review_tag = false;

	public boolean isReview_tag() {
		return review_tag;
	}

	public void setReview_tag(boolean review_tag) {
		AppContext.review_tag = review_tag;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		AppContext.longitude = longitude;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		AppContext.latitude = latitude;
	}

	public void setLogin(boolean login) {
		this.login = login;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		initImageLoader(getApplicationContext());
		// Thread.setDefaultUncaughtExceptionHandler(AppException
		// .getAppExceptionHandler());
	}

	public static void initImageLoader(Context context) {
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				context).threadPriority(Thread.NORM_PRIORITY - 2)
				.denyCacheImageMultipleSizesInMemory()
				.diskCacheFileNameGenerator(new Md5FileNameGenerator())
				.tasksProcessingOrder(QueueProcessingType.LIFO)
				.writeDebugLogs().build();
		ImageLoader.getInstance().init(config);
	}

	public AuthenticateUserResponse authenticateUser(
			CredentialBean credentialBean) {
		AuthenticateUserResponse response = null;
		response = OpenTeeClientProxy.getInstance().authenticateUser(
				credentialBean);
		return response;
	}

	public AuthenticateUserResponse createUserWithExternalAccount(
			ExternalAccount account) {
		AuthenticateUserResponse response = null;
		response = OpenTeeClientProxy.getInstance()
				.createUserWithExternalAccount(account);
		return response;
	}

	public AuthenticateUserResponse register(SignUpBean bean) {
		AuthenticateUserResponse response = null;
		response = OpenTeeClientProxy.getInstance().createUser(bean);
		return response;
	}

	public UpdateUserProfileResponse updateUserProfile(UpdateProfileBean bean) {
		UpdateUserProfileResponse response = null;
		response = OpenTeeClientProxy.getInstance().updateUserProfile(bean);
		return response;
	}

	public ValidateResponse changePassword(UpdatePasswordBean bean) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().changePassword(bean);
		return response;
	}

	public ValidateResponse forgotPassword(String email) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().forgotPassword(email);
		return response;
	}

	public List<PlaceNearBean> locationByNear(LocationNearBean bean)
			throws AppException {
		List<PlaceNearBean> list = null;
		PlaceNearResponse response = null;
		response = OpenTeeClientProxy.getInstance()
				.placesByCountryAndNameNearest(bean);
		if (response != null && !response.isHasError()) {
			list = PlaceNearResponse.parse(response);
		}
		return list;
	}

	public List<PlaceNearBean> locationByName(LocationNearBean bean)
			throws AppException {
		PlaceNearResponse response = null;
		List<PlaceNearBean> list = null;
		response = OpenTeeClientProxy.getInstance()
				.placesByCountryAndNameNearest(bean);
		if (response != null && !response.isHasError()) {
			list = PlaceNearResponse.parse(response);
		}
		return list;
	}

	public List<GolfCourseBean> findTeeTimeByCountryAndNearest(
			FindTeeTimesBean bean, int startIndex, boolean isLogin, int orderBy)
			throws AppException {
		List<GolfCourseBean> list = null;
		FindTeeTimeListViewResponse response = null;
		if (orderBy == Constant.ORDERBY_DISTANCE) {
			response = OpenTeeClientProxy.getInstance()
					.availableTeeTimesByCountryAndNearest(bean, startIndex,
							isLogin);
		} else {
			response = OpenTeeClientProxy.getInstance()
					.availableTeeTimesByCountry(bean, startIndex, isLogin,
							orderBy);
		}
		if (response != null && !response.isHasError()) {
			list = FindTeeTimeListViewResponse.parse(response);
		}
		return list;
	}

	public Map<String, List<GolfCourseBean>> findTeeTimeByCountryRateGroup(
			FindTeeTimesBean bean, boolean isLogin, int startIndex)
			throws AppException {
		Map<String, List<GolfCourseBean>> map = null;
		FindTeeTimePriceResponse response = null;
		response = OpenTeeClientProxy.getInstance()
				.availableTeeTimesByCountryRateGroup(bean, isLogin, startIndex);
		if (response != null && !response.isHasError()) {
			map = FindTeeTimePriceResponse.parse(response);
		}
		return map;
	}

	public GolfCourseDetailBean courseDetail(int courseId) {
		GolfCourseDetailBean golfCourseDetailBean = null;
		GolfCourseDetailResponse response = null;
		response = OpenTeeClientProxy.getInstance().courseDetail(courseId);
		if (response != null && !response.isHasError()) {
			golfCourseDetailBean = response.getData();
		}
		return golfCourseDetailBean;
	}

	public TeeTimesResponse availableTeeTimesByCourseId(int courseId,
			SearchBean bean) {
		TeeTimesResponse response = null;
		response = OpenTeeClientProxy.getInstance()
				.availableTeeTimesByCourseId(courseId, bean);
		return response;
	}

	public ReviewsWriteResponse addCourseReview(ReviewsWriteBean bean) {
		ReviewsWriteResponse response = null;
		response = OpenTeeClientProxy.getInstance().addCourseReview(bean);
		return response;
	}

	public List<ReviewBean> getCourseReviews(int courseId) {
		GolferReviewResponse response = null;
		List<ReviewBean> list = null;
		response = OpenTeeClientProxy.getInstance().getCourseReviews(courseId);
		if (response != null && !response.isHasError()) {
			list = ReviewBean.parse(response.getData());
		}
		return list;
	}

	public ValidateResponse validateTeetime(ValidateBean bean) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().validateTeetime(bean);
		return response;
	}

	public BookingConfirmResponse bookTeeTimeForUser(Boolean flag,
			ConfirmRegisterUserBean confirmRegisterUserBean,
			ConfirmUnregisterUserBean confirmUnregisterUserBean) {
		BookingConfirmResponse bookResponse = null;
		bookResponse = OpenTeeClientProxy.getInstance().bookTeeTimeForUser(
				flag, confirmRegisterUserBean, confirmUnregisterUserBean);
		return bookResponse;
	}

	public BookingConfirmResponse bookAndPayForUser(Boolean flag,
			PaymentRegisterUserBean paymentRegisterUserBean,
			PaymentUnregisterUserBean paymentUnregisterUserBean) {
		BookingConfirmResponse bookResponse = null;
		bookResponse = OpenTeeClientProxy.getInstance().bookAndPayForUser(flag,
				paymentRegisterUserBean, paymentUnregisterUserBean);
		return bookResponse;
	}

	public BookingConfirmationResponse getReservationByReservationId(
			String reservationid) {
		BookingConfirmationResponse response = null;
		response = OpenTeeClientProxy.getInstance()
				.getReservationByReservationId(reservationid);
		return response;
	}

	public ViewMyGolfResponse golfer(String golferId) {
		ViewMyGolfResponse bookResponse = null;
		bookResponse = OpenTeeClientProxy.getInstance().golfer(golferId);
		return bookResponse;
	}

	public List<MyTeeTimesBean> getFutureReservationsByGolfer(String golferId) {
		GetMyTeeTimesResponse response = null;
		List<MyTeeTimesBean> list = null;
		response = OpenTeeClientProxy.getInstance()
				.getFutureReservationsByGolfer(golferId);
		if (response != null && !response.isHasError()) {
			list = GetMyTeeTimesResponse.parse(response);
		}
		return list;
	}

	public ValidateResponse cancelReservation(String reservationid,
			String golferId) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().cancelReservation(
				reservationid, golferId);
		return response;
	}

	public List<MyReviewBean> getMyReviewsByGolfer(String golferId) {
		GetMyReviewsResponse response = null;
		List<MyReviewBean> list = null;
		response = OpenTeeClientProxy.getInstance().getMyReviewsByGolfer(
				golferId);
		if (response != null && !response.isHasError()) {
			list = GetMyReviewsResponse.parse(response);
		}
		return list;
	}

	public GolfCourseDetailBean getMyCourseDetail(String golferId, int courseId) {
		GolfCourseDetailResponse response = null;
		GolfCourseDetailBean bean = new GolfCourseDetailBean();
		response = OpenTeeClientProxy.getInstance().getMyCourseDetail(golferId,
				courseId);
		if (response != null && !response.isHasError()) {
			bean = response.getData();
		}
		return bean;
	}

	public ValidateResponse deleteCourseReview(int courseReviewId,
			String userId, int courseId) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().deleteCourseReview(
				courseReviewId, userId, courseId);
		return response;
	}

	public ValidateResponse updateCourseReview(ReviewsUpdateBean bean) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().updateCourseReview(bean);
		return response;
	}

	public List<MyFavoriteBean> getMyFavoriteCourses(String golferId) {
		GetMyFavoriteResponse response = null;
		List<MyFavoriteBean> list = new ArrayList<MyFavoriteBean>();
		response = OpenTeeClientProxy.getInstance().getMyFavoriteCourses(
				golferId);
		if (response != null && !response.isHasError()) {
			list = GetMyFavoriteResponse.parse(response);
		}
		return list;
	}

	public ValidateResponse addFavoriteCourse(String golferId, int courseId) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().addFavoriteCourse(golferId,
				courseId);
		return response;
	}

	public ValidateResponse removeFavoriteCourse(String golferId, int courseId) {
		ValidateResponse response = null;
		response = OpenTeeClientProxy.getInstance().removeFavoriteCourse(
				golferId, courseId);
		return response;
	}

	public BookingConfirmationResponse getReservationByConfirmationIdAndEmail(
			FindBookingBean findBookingBean) {
		BookingConfirmationResponse response = null;
		response = OpenTeeClientProxy.getInstance()
				.getReservationByConfirmationIdAndEmail(findBookingBean);
		return response;
	}

	public boolean isNetworkConnected() {
		ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		return ni != null && ni.isConnectedOrConnecting();
	}

	public boolean checkConnect(Context ctx) {
		try {
			ConnectivityManager conMgr = (ConnectivityManager) ctx
					.getSystemService(Context.CONNECTIVITY_SERVICE);

			if (conMgr.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED
					|| conMgr.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED) {
				return true;
			} else if (conMgr.getNetworkInfo(0).getState() == NetworkInfo.State.DISCONNECTED
					|| conMgr.getNetworkInfo(1).getState() == NetworkInfo.State.DISCONNECTED) {
				return false;
			}
		} catch (Exception e) {
		}

		return false;
	}

	public PackageInfo getPackageInfo() {
		PackageInfo info = null;
		try {
			info = getPackageManager().getPackageInfo(getPackageName(), 0);
		} catch (NameNotFoundException e) {
			e.printStackTrace(System.err);
		}
		if (info == null)
			info = new PackageInfo();
		return info;
	}

	public boolean isLogin() {
		return login;
	}

	public boolean isReadDataCache(String cachefile) {
		return readObject(cachefile) != null;
	}

	private boolean isExistDataCache(String cachefile) {
		boolean exist = false;
		File data = getFileStreamPath(cachefile);
		if (data.exists())
			exist = true;
		return exist;
	}

	public boolean saveObject(Serializable ser, String file) {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			fos = openFileOutput(file, MODE_PRIVATE);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(ser);
			oos.flush();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				oos.close();
			} catch (Exception e) {
			}
			try {
				fos.close();
			} catch (Exception e) {
			}
		}
	}

	public Serializable readObject(String file) {
		if (!isExistDataCache(file)) {
			return null;
		}
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
			fis = openFileInput(file);
			ois = new ObjectInputStream(fis);
			return (Serializable) ois.readObject();
		} catch (FileNotFoundException e) {
		} catch (Exception e) {
			e.printStackTrace();

			if (e instanceof InvalidClassException) {
				File data = getFileStreamPath(file);
				data.delete();
			}
		} finally {
			try {
				ois.close();
			} catch (Exception e) {
			}
			try {
				fis.close();
			} catch (Exception e) {
			}
		}
		return null;
	}

	public void deleteObject(String file) {
		if (!isExistDataCache(file)) {
			return;
		}
		File data = getFileStreamPath(file);
		data.delete();
	}

	public void Logout() {
		UserInfoBean userInfoBean = getLoginInfo();
		userInfoBean.getUser().setHasPassword(false);
		saveLoginInfo(userInfoBean);
		this.cleanCookie();
		this.login = false;
	}

	@SuppressWarnings("serial")
	public void saveLoginInfo(final UserInfoBean userInfoBean) {
		this.login = true;
		final UserBean user = userInfoBean.getUser();
		setProperties(new Properties() {
			{
				setProperty("user.email", user.getEmail());
				setProperty("user.password", userInfoBean.getPassword());
				setProperty("user.userId", user.getUserId());
				setProperty("user.golferId", user.getGolferId());
				setProperty("user.hasPassword",
						String.valueOf(user.isHasPassword()));
				setProperty("user.firstname", user.getFirstName());
				setProperty("user.lastname", user.getLastName());
				setProperty("user.phoneNumber", user.getPhoneNumber());
				setProperty("user.gender", user.getGender());
				setProperty("user.dateOfBirth", user.getDateOfBirth());
				setProperty("user.created", user.getCreated());
				setProperty("user.mobileNumber", user.getMobileNumber());
				setProperty("user.address", user.getAddress());
				setProperty("user.address2", user.getAddress2());
				setProperty("user.city", user.getCity());
				setProperty("user.zipCode", user.getZipCode());
				setProperty("user.stateCode", user.getStateCode());
				setProperty("user.country2IsoCode", user.getCountry2IsoCode());
			}
		});
	}

	public void cleanLoginInfo() {
		this.login = false;
		removeProperty("user.email", "user.password", "user.userId",
				"user.golferId", "user.hasPassword", "user.firstname",
				"user.lastname", "user.phoneNumber", "user.gender",
				"user.dateOfBirth", "user.created", "user.mobileNumber",
				"user.address", "user.address2", "user.city", "user.zipCode",
				"user.stateCode", "user.country2IsoCode");
	}

	public UserInfoBean getLoginInfo() {
		UserInfoBean userInfoBean = new UserInfoBean();
		UserBean user = new UserBean();
		user.setEmail(getProperty("user.email"));
		userInfoBean.setPassword(getProperty("user.password"));
		user.setUserId(getProperty("user.userId"));
		user.setGolferId(getProperty("user.golferId"));
		user.setHasPassword(StringUtils.toBool(getProperty("user.hasPassword")));
		user.setFirstName(getProperty("user.firstname"));
		user.setLastName(getProperty("user.lastname"));
		user.setPhoneNumber(getProperty("user.phoneNumber"));
		user.setGender(getProperty("user.gender"));
		user.setDateOfBirth(getProperty("user.dateOfBirth"));
		user.setCreated(getProperty("user.created"));
		user.setMobileNumber(getProperty("user.mobileNumber"));
		user.setAddress(getProperty("user.address"));
		user.setAddress2(getProperty("user.address2"));
		user.setCity(getProperty("user.city"));
		user.setZipCode(getProperty("user.zipCode"));
		user.setStateCode(getProperty("user.stateCode"));
		user.setCountry2IsoCode(getProperty("user.country2IsoCode"));
		userInfoBean.setUser(user);
		return userInfoBean;
	}

	public boolean containsProperty(String key) {
		Properties props = getProperties();
		return props.containsKey(key);
	}

	public void setProperties(Properties ps) {
		if (appConfig == null) {
			appConfig = new AppConfig();
		}
		appConfig.getAppConfig(this).set(ps);
	}

	public Properties getProperties() {
		if (appConfig == null) {
			appConfig = new AppConfig();
		}
		return appConfig.getAppConfig(this).get();
	}

	public void setProperty(String key, String value) {
		if (appConfig == null) {
			appConfig = new AppConfig();
		}
		appConfig.getAppConfig(this).set(key, value);
	}

	public String getProperty(String key) {
		if (appConfig == null) {
			appConfig = new AppConfig();
		}
		return appConfig.getAppConfig(this).get(key);
	}

	public void removeProperty(String... key) {
		if (appConfig == null) {
			appConfig = new AppConfig();
		}
		appConfig.getAppConfig(this).remove(key);
	}

	public void cleanCookie() {
		removeProperty(AppConfig.CONF_COOKIE);
	}

	public int getSDKVersionNumber() {
		int sdkVersion;
		try {
			sdkVersion = Integer.valueOf(android.os.Build.VERSION.SDK);
		} catch (NumberFormatException e) {
			sdkVersion = 0;
		}
		return sdkVersion;
	}
}
